﻿\subsection{Конвертирование 32-битного значения в 64-битное}
\label{subsec:sign_extending_32_to_64}

\lstinputlisting[style=customc]{patterns/185_64bit_in_32_env/conversion/4.c}

\subsubsection{x86}

\lstinputlisting[caption=\Optimizing MSVC 2012,,style=customasmx86]{patterns/185_64bit_in_32_env/conversion/MSVC2012_Ox.asm}

Здесь появляется необходимость расширить 32-битное знаковое значение в 64-битное знаковое.

Конвертировать беззнаковые значения очень просто: нужно просто выставить в 0 все биты в старшей части.
Но для знаковых типов это не подходит: знак числа должен быть скопирован в старшую часть числа-результата.
\myindex{x86!\Instructions!CDQ}
Здесь это делает инструкция \INS{CDQ}, она берет входное значение в \EAX{}, расширяет его до 64-битного,
и оставляет его в паре регистров \EDX{}:\EAX{}.
Иными словами, инструкция \INS{CDQ} узнает знак числа в \EAX{} (просто берет самый старший бит в \EAX{}) и в зависимости от этого,
выставляет все 32 бита в \EDX{} в 0 или в 1.
Её работа в каком-то смысле напоминает работу инструкции \MOVSX{}.

\subsubsection{ARM}

\lstinputlisting[caption=\OptimizingKeilVI (\ARMMode),style=customasmARM]{patterns/185_64bit_in_32_env/conversion/Keil_ARM_O3.s}

Keil для ARM работает иначе: он просто сдвигает (арифметически) входное значение на 31 бит вправо.
Как мы знаем, бит знака это \ac{MSB}, и арифметический сдвиг копирует бит знака в \q{появляющихся} битах.

Так что после инструкции \INS{ASR r1,r0,\#31}, \Reg{1} будет содержать 0xFFFFFFFF если входное значение
было отрицательным, или 0 в противном случае.
\Reg{1} содержит старшую часть возвращаемого 64-битного значения.
Другими словами, этот код просто копирует \ac{MSB} (бит знака) из входного значения в \Reg{0} во все
биты старшей 32-битной части итогового 64-битного значения.

\subsubsection{MIPS}

GCC для MIPS делает то же, что сделал Keil для режима ARM:

\lstinputlisting[caption=\Optimizing GCC 4.4.5 (IDA),style=customasmMIPS]{patterns/185_64bit_in_32_env/conversion/MIPS_O3_IDA.lst}

